﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Narwhunderful.Aphelia.Framework.Graphics
{

    public static class DrawingHelper
    {

        public static Rectangle RectangleIntersect(Rectangle rectangle1, Rectangle rectangle2)
        {
            int x = Math.Max(rectangle1.X, rectangle2.X);
            int y = Math.Max(rectangle1.Y, rectangle2.Y);
            int right = Math.Min(rectangle1.Right, rectangle2.Right);
            int bottom = Math.Min(rectangle1.Bottom, rectangle2.Bottom);
            if ((right > x) && (bottom > y))
            {
                return new Rectangle(x, y, right - x, bottom - y);
            }
            else
            {
                return Rectangle.Empty;
            }
        }

        public static bool PixelsIntersect(Rectangle rectangle1, Color[] data1, Rectangle rectangle2, Color[] data2)
        {
            Rectangle intersectRectangle = RectangleIntersect(rectangle1, rectangle2);

            for (int y = intersectRectangle.Top; y < intersectRectangle.Bottom; y++)
            {
                for (int x = intersectRectangle.Left; x < intersectRectangle.Right; x++)
                {
                    Color pixel1 = data1[(x - rectangle1.Left) + (y - rectangle1.Top) * rectangle1.Width];
                    Color pixel2 = data2[(x - rectangle2.Left) + (y - rectangle2.Top) * rectangle2.Width];
                    if (pixel1.A != 0 && pixel2.A != 0) return true;
                }
            }

            return false;
        }

        public static bool PixelsTransformedIntersect(Matrix transform1, Rectangle cacheRectangle1, Color[] data1, Matrix transform2, Rectangle cacheRectangle2, Color[] data2)
        {
            Matrix transform1To2 = transform1 * Matrix.Invert(transform2);
            Vector2 stepX = Vector2.TransformNormal(Vector2.UnitX, transform1To2);
            Vector2 stepY = Vector2.TransformNormal(Vector2.UnitY, transform1To2);
            Vector2 topLeftIn2 = Vector2.Transform(Vector2.Zero, transform1To2);
            Vector2 posIn2;
            int x1, y1, x2, y2;

            for (y1 = 0; y1 < cacheRectangle1.Height; y1++)
            {
                posIn2 = topLeftIn2;
                for (x1 = 0; x1 < cacheRectangle1.Width; x1++)
                {
                    x2 = (int)Math.Round(posIn2.X);
                    y2 = (int)Math.Round(posIn2.Y);

                    if (x2 >= 0 && x2 < cacheRectangle2.Width && y2 >= 0 && y2 < cacheRectangle2.Height)
                    {
                        Color pixel1 = data1[x1 + y1 * cacheRectangle1.Width];
                        Color pixel2 = data2[x2 + y2 * cacheRectangle2.Width];

                        if (pixel1.A != 0 && pixel2.A != 0) return true;
                    }
                    posIn2 += stepX;
                }
                topLeftIn2 += stepY;
            }
            return false;
        }

        public static Rectangle GetTransformedRectangle(Matrix worldTransform, Rectangle rectangle)
        {
            Vector2 topLeft = new Vector2(rectangle.Left, rectangle.Top);
            Vector2 topRight = new Vector2(rectangle.Right, rectangle.Top);
            Vector2 bottomLeft = new Vector2(rectangle.Left, rectangle.Bottom);
            Vector2 bottomRight = new Vector2(rectangle.Right, rectangle.Bottom);

            Vector2.Transform(ref topLeft, ref worldTransform, out topLeft);
            Vector2.Transform(ref topRight, ref worldTransform, out topRight);
            Vector2.Transform(ref bottomLeft, ref worldTransform, out bottomLeft);
            Vector2.Transform(ref bottomRight, ref worldTransform, out bottomRight);

            Vector2 min = Vector2.Min(Vector2.Min(topLeft, topRight), Vector2.Min(bottomLeft, bottomRight));
            Vector2 max = Vector2.Max(Vector2.Max(topLeft, topRight), Vector2.Max(bottomLeft, bottomRight));

            return new Rectangle((int)min.X, (int)min.Y, (int)(max.X - min.X), (int)(max.Y - min.Y));
        }

    }

}
